/***********************************************************************************************//**
 * \file   event_control.h
 * \brief  SW Timer
 ***************************************************************************************************
 * <b> (C) Copyright 2015 Silicon Labs, http://www.silabs.com</b>
 ***************************************************************************************************
 * This file is licensed under the Silabs License Agreement. See the file
 * "Silabs_License_Agreement.txt" for details. Before using this software for
 * any purpose, you must agree to the terms of that agreement.
 **************************************************************************************************/

#ifndef EVENT_CONTROL_H
#define EVENT_CONTROL_H

#ifdef __cplusplus
extern "C" {
#endif

/***********************************************************************************************//**
 * \defgroup evt_ctrl Event Control
 * \brief Implements EMLib RTCC based SW TIMER for the stack and the application.
 **************************************************************************************************/

/***********************************************************************************************//**
 * @addtogroup Platform
 * @{
 **************************************************************************************************/

/***********************************************************************************************//**
 * @addtogroup evt_ctrl
 * @{
 **************************************************************************************************/

/***************************************************************************************************
  Data Types
***************************************************************************************************/

/* Event status enumeration */
typedef enum
{
  /** The event is not scheduled to run. */
  EVENT_INACTIVE   = 0,
  /** The execution time is in approximate milliseconds.  */
  EVENT_MS_TIME    = 1,
  /** The event is scheduled to run at the earliest opportunity. */
  EVENT_ZERO_DELAY = 2
} EmberEventUnits;

/***********************************************************************************************//**
 *  \brief  Control structure for events.
 *  \return  This structure should not be accessed directly.
 * This holds the event status  and the time left before the event fires.
 **************************************************************************************************/
typedef struct {
  /** The event's status, either inactive or the units for timeToExecute. */
  EmberEventUnits status;
  /** How long before the event fires. */
  uint32_t timeToExecute;
} EmberEventControl;

/***********************************************************************************************//**
 *  \brief  Complete events with a control and a handler procedure.
 *  \return  An application typically creates an array of events along with their handlers.
 * The main loop passes the array to runEvents() in order to call the handlers of any events whose
 * time has arrived.
 **************************************************************************************************/
typedef const struct {
  /** The control structure for the event. */
  EmberEventControl *control;
  /** The procedure to call when the event fires. */
  void (*handler)(void);
} EmberEventData;

/***************************************************************************************************
  Public Macros and Definitions
***************************************************************************************************/

/***********************************************************************************************//**
 *  \brief  Elapsed time
 *  \return  Returns the elapsed time between two 32 bit values.
 *  Result may not be valid if the time samples differ by more than 2^32-1
 **************************************************************************************************/
#define elapsedTimeInt32u(oldTime, newTime)  ((uint32_t)((uint32_t)(newTime) - (uint32_t)(oldTime)))

/***********************************************************************************************//**
 *  \brief  Comparison of time stamps.
 *  \return  Returns TRUE if t1 is greater than t2.  Can only account for 1 wrap
 * around of the variable before it is wrong..
 **************************************************************************************************/
#define MAX_INT32U_VALUE      (0xFFFFFFFFL)
#define HALF_MAX_INT32U_VALUE (0x80000000L)
#define timeGTorEqualInt32u(t1, t2)  (elapsedTimeInt32u(t2, t1) <= (HALF_MAX_INT32U_VALUE))

/***********************************************************************************************//**
 *  \brief  Set Timer to Inactive.
 **************************************************************************************************/
#define eventControlSetInactive(control)   \
do { (control).status = EVENT_INACTIVE; } while(0)

/***************************************************************************************************
  Extern Variables
***************************************************************************************************/
extern EmberEventData stackEvts[];
extern EmberEventData emAppEvents[];

/***************************************************************************************************
  Public Function Declarations
***************************************************************************************************/

/***********************************************************************************************//**
 *  \brief  SW Timer Handling.
 *  \return  Periodically called event handler which checks all SW timer states and executes their
 *  handler function if necessary.
 **************************************************************************************************/
void runEvents(void);

/***********************************************************************************************//**
 *  \brief  Set SW Timer to a specific value.
 *  \return  Set a delay in [ms], after which the handler function of the event will be triggered.
 **************************************************************************************************/
void eventControlSetDelayMS(EmberEventControl*event, uint16_t delay);

/***********************************************************************************************//**
 *  \brief  Set SW Timer to a specific value.
 *  \return  Set a delay in [quarters], after which the handler function of the event will be
 *  triggered.
 **************************************************************************************************/
void eventControlSetDelayQS(EmberEventControl*event, uint16_t delay);

/***********************************************************************************************//**
 *  \brief  Set SW Timer to a specific value.
 *  \return  Set a delay in [minutes], after which the handler function of the event will be
 *  triggered.
 **************************************************************************************************/
void eventControlSetDelayMinutes(EmberEventControl*event, uint16_t delay);

/***********************************************************************************************//**
 *  \brief  Get time to next event.
 *  @param events  Pointer to array of events.
 *  @param maxMs  Maximum time interval to sleep for in milliseconds.
 *  \return  Get the number of milliseconds remaining until the next event.
 **************************************************************************************************/
uint32_t msToNextEvent(EmberEventData *events, uint32_t maxMs);


/** @} (end addtogroup evt_ctrl) */
/** @} (end addtogroup Platform) */

#ifdef __cplusplus
};
#endif

#endif // EVENT_CONTROL_H

